文章结构:
1)AbstractQueuedSynchronizer介绍:
2)继承树分析
3)形象说明其原理
4)源码阅读分析
5)思考几个问题
一、AbstractQueuedSynchronizer介绍:
(1)简介:
AbstractQueuedSynchronizer(AQS)抽象类提供一个实现阻塞锁和依赖于FIFO等待队列的同步器的框架。
使用方式是继承它作为一个内部辅助类实现同步原语,它可以简化你的并发工具的内部实现,屏蔽同步状态管理、线程的排队、等待与唤醒等底层操作。
AQS被设计用来作为众多同步器的基类,例如ReentrantLock、Semaphore、CountDownLatch、FutureTask以及ReentrantReadWriteLock。
(2)不同的同步器对状态的含义解释不同:
1)在ReentrantLock中,AQS的同步状态用于保存锁获取操作的次数
ReentrantLock: 使用了AQS的独占获取和释放,用state变量记录某个线程获取独占锁的次数,获取锁时+1,释放锁时-1,在获取时会校验线程是否可以获取锁
2)在FutureTask中,AQS同步状态被用来保存任务的状态;
3)在Semaphore和CountDownLatch中,AQS的同步状态用于保存当前可用许可的数量;
使用了AQS的共享获取和释放,用state变量作为计数器,只有在大于0时允许线程进入。获取锁时-1,释放锁时+1。
4)CountDownLatch,用state变量作为计数器:
使用了AQS的共享获取和释放,用state变量作为计数器,在初始化时指定。只要state还大于0,获取共享锁会因为失败而阻塞,直到计数器的值为0时,共享锁才允许获取,所有等待线程会被逐一唤醒。
针对AQS中的状态,只可以通过AQS的getState()、setState()和compareAndSetState()方法来原子式改变状态。
(3)支付独占锁与非独占锁:
AQS同时支持独占操作模式(例如ReentrantLock)和非独占操作模式(例如Semaphore和CountDownLatch)。
当以独占模式获取锁时,只有一个线程能访问成功,其他线程都访问失败;而以非独占模式获取锁时,多个线程可以同时访问成功。
不同操作模式的线程都在同一个FIFO队列中等待。通常,AQS的子类只支持一种操作模式(独占或非独占),但也有同时支持两种操作模式的同步器,例如ReadWriteLock的子类,它的读取锁是非独占操作模式,而写入锁是独占操作模式。
二、继承树分析:
(1)Lock接口:
JUC包中的 Lock 接口支持那些语义不同(重入、公平等)的锁规则。
所谓语义不同,是指锁可是有"公平机制的锁"、“非公平机制的锁”、“可重入的锁"等等。“公平机制"是指"不同线程获取锁的机制是公平的”,而"非公平机制"则是指"不同线程获取锁的机制是非公平的”,"可重入的锁"是指同一个锁能够被一个线程多次获取。
(2)ReadWriteLock接口:
ReadWriteLock 接口以和Lock类似的方式定义了一些读取者可以共享而写入者独占的锁。
JUC包只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。
(3)AbstractOwnableSynchronizer/AbstractQueuedSynchronizer
AbstractQueuedSynchronizer也就是我们常说的AQS,可用来定义锁以及依赖于排队阻塞线程的其他同步器;ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等这些类都是基于AQS类实现的。
(4)ReentrantLock
ReentrantLock可重入独占锁。后面会详述此锁。
(5) ReentrantReadWriteLock
ReentrantReadWriteLock是读写锁接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReentrantLock是共享锁,而WriteLock是独占锁。
(6)CountDownLatch
CountDownLatch,是线程同步辅助类,在一组线程中,可以让已完成的线程一直等待未完成的线程完成。
(7)CyclicBarrier
CyclicBarrier,是一个同步辅助类,可以实现让一组线程互相等待,直到某一状态后(common barrier point公共屏障点)再全部同时执行(并发动作)。而且barrier在释放等待线程后可以重复使用,所以称为循环的barrier。
(8)Semaphore
Semaphore是一个计数信号量,它的本质是一个"共享锁"。通常用来限制可以访问资源的线程数量,使他们能够正确、合理地使用公共资源。
(9)LockSupport
LockSupport提供“创建锁”和“其他同步类的基本线程阻塞原语”。
LockSupport的功能和"Thread中的Thread.suspend()和Thread.resume()有点类似",LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。但是park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
(10)Condition
其实condition就是维护一个条件队列,需要和Lock联合使用,它的作用是代替Object监视器方法,可以通过await(),signal()来休眠/唤醒线程。
Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。
(11)Sync
是一个抽象内部类,是各个锁实现锁获取、锁释放、判断资源是否被当前线程占有等等功能
(12)FairSync和NonfairSync
分别继承Sync,实现公平锁和非公平锁。
三、形象说明其原理:
(1)同步队列的维护:
其实一个双向链表队列。一个FIFO双向队列,AQS依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。
(2)同步状态的管理:
其实就是waitStatus的状态值管理。
设计背景:如果获取锁失败,判断是否应该挂起当前线程,可以看见挂起线程是有条件的。
1)SIGNAL:
该节点的后继节点当前是阻塞的,因此当前节点在释放和取消之后,必须唤醒它的后继节点。为了避免竞争,acquire方法必须首先进入SIGNAL等着状态,然后再尝试原子获取,这个获取过程可能会失败或者阻塞。
2)CANCELLED:
该节点由于超时或者中断了被取消了。节点进入了CANCELLED状态之后,就不会再发生状态的变化了。特别地,处于CANCELLED状态节点的线程不会再被阻塞了。这个状态的结点会踢出队列,被GC回收。
3)CONDITION:
该节点当前处于一个条件队列中。经过转移之后,该节点将会被作为同步队列的节点使用,此时节点的状态会被设置为0。
4)PROPAGATE:
使用在共享模式头结点有可能处于这种状态表示锁的下一次获取可以无条件传播。
5)0:
非以上任何状态。新结点处于这种状态
(3)线程阻塞和唤醒:
检查当前线程是否需要被阻塞主要还是根据同步状态waitStatus进行管理。
当需要阻塞或者唤醒一个线程的时候,AQS都是使用LockSupport这个工具类来完成的。
每个使用LockSupport的线程都会与一个许可关联,如果该许可可用,并且可在进程中使用,则调用park()将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。但是注意许可不可重入,也就是说只能调用一次park()方法,否则会一直阻塞。
四、源码阅读分析:
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
protected AbstractOwnableSynchronizer() { }
//用来保存是哪个线程获得了独占锁或者写锁,当该值为null时,表示没有线程获得独占锁或者写锁。
private transient Thread exclusiveOwnerThread;
//设置当前拥有独占访问的线程。
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
// 返回由 setExclusiveOwnerThread 最后设置的线程;如果从未设置,则返回 null。
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
AbstractQueuedSynchronizer继承自AbstractOwnableSynchronizer抽象类,并且实现了Serializable接口,可以进行序列化。
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
//嵌套类Node
static final class Node {
/** 用于标记一个节点在共享模式下等待*/
static final Node SHARED = new Node();
/**用于标记一个节点在独占模式下等待*/
static final Node EXCLUSIVE = null;
/** 等待状态:取消 */
static final int CANCELLED = 1;
/** 等待状态:通知 */
static final int SIGNAL = -1;
/**等待状态:条件等待 */
static final int CONDITION = -2;
/**
等待状态:传播
*/
static final int PROPAGATE = -3;
//等待状态
/*
1.SIGNAL:该节点的后继节点当前是阻塞的,因此当前节点在释放和取消之后,必须唤醒它的后继节点。为了避免竞争,acquire方法必须首先进入SIGNAL等着状态,然后再尝试原子获取,这个获取过程可能会失败或者阻塞。
2.CANCELLED:该节点由于超时或者中断了被取消了。节点进入了CANCELLED状态之后,就不会再发生状态的变化了。特别地,处于CANCELLED状态节点的线程不会再被阻塞了。
3.CONDITION:该节点当前处于一个条件队列中。经过转移之后,该节点将会被作为同步队列的节点使用,此时节点的状态会被设置为0。
4.PROPAGATE:releaseShared方法应该传递给其他Node节点。在doReleaseShared方法中,确保传递会继续。
5.0:非以上任何状态;
*/
volatile int waitStatus;
//前驱节点
volatile Node prev;
//后继节点
volatile Node next;
//节点对应的线程
volatile Thread thread;
//等待队列中的后继节点
Node nextWaiter;
/**
* 当前节点是否处于共享模式等待
*/
final boolean isShared() {
return nextWaiter == SHARED;
}
/**
获取前驱节点,如果为空的话抛出空指针异常
*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { //addWaiter会调用此构造函数
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Condition会用到此构造函数
this.waitStatus = waitStatus;
this.thread = thread;
}
}
//等待队列头指针
private transient volatile Node head;
//等待队列尾指针
private transient volatile Node tail;
//同步状态(state为0时,无锁,当state>0时说明有锁。
private volatile int state;
//获取锁状态
protected final int getState() {
return state;
}
//设置锁状态
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
///自旋时间spinForTimeoutThreshold
static final long spinForTimeoutThreshold = 1000L;
// 入队列,enq函数会使用无限循环来确保节点的成功插入。
private Node enq(final Node node) {
// 无限循环,确保结点能够成功入队列
for (;;) {
// 保存尾结点
Node t = tail;
// 尾结点为空,即还没被初始化
if (t == null) { // Must initialize
// 头结点为空,并设置头结点为新生成的结点
if (compareAndSetHead(new Node()))
// 头结点与尾结点都指向同一个新生结点
tail = head;
} else {
// 尾结点不为空,即已经被初始化过,将node结点的prev域连接到尾结点
node.prev = t;
// 比较结点t是否为尾结点,若是则将尾结点设置为node
if (compareAndSetTail(t, node)) {
// 设置尾结点的next域为node
t.next = node;
// 返回尾结点
return t;
}
}
}
}
// 添加等待者
private Node addWaiter(Node mode) {
// 新生成一个结点,默认为独占模式
Node node = new Node(Thread.currentThread(), mode);
// 保存尾结点
Node pred = tail;
if (pred != null) {
node.prev = pred;
// 比较pred是否为尾结点,是则将尾结点设置为node
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
// 设置头结点
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
// 释放node的前一个结点
private void unparkSuccessor(Node node) {
// 获取node结点的等待状态
int ws = node.waitStatus;
if (ws < 0)
// 比较并且设置结点等待状态,设置为0
compareAndSetWaitStatus(node, ws, 0);
// 获取node节点的下一个结点
Node s = node.next;
// 下一个结点为空或者下一个节点的等待状态大于0,即为CANCELLED
if (s == null || s.waitStatus > 0) {
// s赋值为空
s = null;
// 从尾结点开始从后往前开始遍历
for (Node t = tail; t != null && t != node; t = t.prev)
// 找到等待状态小于等于0的结点,找到最前的状态小于等于0的结点
if (t.waitStatus <= 0)
// 保存结点
s = t;
}
// 该结点不为为空,释放许可
if (s != null)
LockSupport.unpark(s.thread);
}
/*
主要是唤醒后继节点。对于能够支持多个线程同时访问的并发组件(比如Semaphore),它和独占式主要区别在于tryReleaseShared(int arg)方法必须确保同步状态(或者资源数)线程安全释放,一般是通过循环和CAS来保证的,因为释放同步状态的操作会同时来自多个线程。
*/
private void doReleaseShared() {
//死循环保证释放
for (;;) {
// 获取队列的头节点
Node h = head;
// 如果头节点不为null,并且头节点不等于tail节点
if (h != null && h != tail) {
// 获取头节点对应的线程的状态
int ws = h.waitStatus;
// 如果头节点对应的线程是SIGNAL状态,则意味着“头节点的下一个节点所对应的线程”需要被unpark唤醒
if (ws == Node.SIGNAL) {
// 设置“头节点对应的线程状态”为空状态。失败的话,则继续循环。
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
// 唤醒“头节点的下一个节点所对应的线程”。
unparkSuccessor(h);
}
// 如果头节点对应的线程是空状态,则设置“尾节点对应的线程所拥有的共享锁”为其它线程获取锁的空状态。
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
// 如果头节点发生变化,则继续循环。否则,退出循环。
if (h == head) // loop if head changed
break;
}
}
//当前节点设置为队列头
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node);
//如果propagate >0,说明共享锁还有可以进行获得锁,继续唤醒下一个节点
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
//唤醒后继线程
doReleaseShared();
}
}
// Utilities for various versions of acquire
// 取消继续获取(资源)
private void cancelAcquire(Node node) {
// node为空,返回
if (node == null)
return;
// 设置node结点的thread为空
node.thread = null;
// Skip cancelled predecessors
// 保存node的前驱结点
Node pred = node.prev;
// 找到node前驱结点中第一个状态小于0的结点,即不为CANCELLED状态的结点
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
// 获取pred结点的下一个结点
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
// 设置node结点的状态为CANCELLED
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
// node结点为尾结点,则设置尾结点为pred结点
if (node == tail && compareAndSetTail(node, pred)) {
// 比较并设置pred结点的next节点为null
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
// node结点不为尾结点,或者比较设置不成功
int ws;
// (pred结点不为头结点,并且pred结点的状态为SIGNAL)或者 pred结点状态小于等于0,并且比较并设置等待状态为SIGNAL成功,并且pred结点所封装的线程不为空
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
// 保存结点的后继
Node next = node.next;
// 后继不为空并且后继的状态小于等于0
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
// 释放node的前一个结点
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
// 当获取(资源)失败后,检查并且更新结点状态
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
// 获取前驱结点的状态
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
// 可以进行park操作
return true;
// 表示状态为CANCELLED,为1
if (ws > 0) {
// 找到pred结点前面最近的一个状态不为CANCELLED的结点
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
// 赋值pred结点的next域
pred.next = node;
} else {
// 为PROPAGATE -3 或者是0 表示无状态,(为CONDITION -2时,表示此节点在condition queue中)
// 比较并设置前驱结点的状态为SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
// 不能进行park操作
return false;
}
//中断自己一下
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
// 进行park操作并且返回该线程是否被中断
private final boolean parkAndCheckInterrupt() {
// 在许可可用之前禁用当前线程,并且设置了blocker
LockSupport.park(this);
// 当前线程是否已被中断,并清除中断标记位
return Thread.interrupted();
}
/* 核心方法*/
// sync队列中的结点在独占且忽略中断的模式下获取(资源)
final boolean acquireQueued(final Node node, int arg) {
// 标志
boolean failed = true;
try {
// 中断标志
boolean interrupted = false;
//死循环
for (;;) {
// 获取node节点的前驱结点
final Node p = node.predecessor();
// 前驱为头结点并且成功获得锁
if (p == head && tryAcquire(arg)) {
// 设置头结点
setHead(node);
p.next = null; // help GC
// 设置标志
failed = false;
return interrupted;
}
// 当获取(资源)失败后,检查并且更新结点状态,进行park操作并且返回该线程是否被中断
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//中断标记
interrupted = true;
}
} finally {
//有中断标记就 取消继续获取(资源)
if (failed)
cancelAcquire(node);
}
}
/*
与acquireQueued
关键的区别在于检测到interrupted后的处理,acquireQueued简单的记录下中断曾经发生,然后就象没事人似的去尝试获取锁,失败则休眠。而doAcquireInterruptibly检测到中断则直接退出循环,抛出InterruptedException异常。
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//抛异常
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//独占超时获得锁
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
//计算出超时时间点
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
//计算剩余超时时间,超时时间点deadline减去当前时间点System.nanoTime()得到还应该睡眠的时间
nanosTimeout = deadline - System.nanoTime();
//如果超时,返回false,获取锁失败
if (nanosTimeout <= 0L)
return false;
//判断是否需要阻塞当前线程
//如果需要,在判断当前剩余纳秒数是否大于1000
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
//阻塞 nanosTimeout纳秒数
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//通过doAcquireShared()进入等待队列,直到获取到资源为止才返回。
private void doAcquireShared(int arg) {
//构建共享Node
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;){
//获取前驱节点
final Node p = node.predecessor();
//如果是头节点进行尝试获得锁
if (p == head) {
//如果返回值大于等于0,则说明获得锁
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//将当前线程放入到队列中去
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
//将当前线程包装为类型为Node.SHARED的节点,标示这是一个共享节点。
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
//如果新建节点的前一个节点,就是Head,说明当前节点是AQS队列中等待获取锁的第一个节点,
//按照FIFO的原则,可以直接尝试获取锁。
int r = tryAcquireShared(arg);
if (r >= 0) {
//获取成功,需要将当前节点设置为AQS队列中的第一个节点
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//检查下是否需要将当前节点挂起
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//实现超时时间的控制的。
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
//每次循环的时候用当前时间和“deadline”比较,大于“dealine”说明超时时间已到
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
//拿超时时间和超时自旋的最小作比较,只有超时时间大于1000ns才会去挂起线程,否则,再次循环,以实现“自旋”操作
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
/**
核心方法:以独占模式获取(资源),忽略中断,即线程在aquire过程中,中断此线程是无效的
会一直阻塞,直到获得锁,不需要返回值。
*/
public final void acquire(int arg) {
//尝试获得锁,获取不到则加入到队列中等待获取
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
/**
方法会一直阻塞,直到获取锁或者被打断抛出中断异常,不需要返回值。
*/
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
/**
方法会阻塞到获取锁返回true表示获得了锁,或者被打断抛出异常,或者到超时,返回false表示没有获得锁。
*/
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
/**
以独占模式释放对象
*/
public final boolean release(int arg) {
// 释放成功
if (tryRelease(arg)) {
// 保存头结点
Node h = head;
// 头结点不为空并且头结点状态不为0
if (h != null && h.waitStatus != 0)
//释放头结点的后继结点
unparkSuccessor(h);
return true;
}
return false;
}
/**
获得共享锁
*/
public final void acquireShared(int arg) {
//尝试获取的锁,如果获取失败执行doAcquireShared方法,直到获取到资源为止才返回。
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
/**
响应线程的打断的
*/
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
//检查下线程是否被打断
if (Thread.interrupted())
throw new InterruptedException();
//尝试着获取共享锁,小于0,表示获取失败
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
/**
此方法引入了自旋锁
第二个参数为超时时间,如果超时时间很短,则不让线程挂起,而是通过自旋代替,这样线程获得锁很快就释放的情况下能消耗少量的cpu资源节省线程挂起和恢复的性能损耗。
*/
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
//共享模式下释放锁
public final boolean releaseShared(int arg) {
//首先会去验证一下能否释放锁
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
// Queue inspection methods
/**
有没有线程在排队,判断条件是head == tail
*/
public final boolean hasQueuedThreads() {
return head != tail;
}
/**
查询是否其他线程也曾争则获取此同步器,也就是说acquire是否已经阻塞,是则返回true。
*/
public final boolean hasContended() {
return head != null;
}
/**
返回当前同步队列中的第一个线程,没有有则返回null。
*/
public final Thread getFirstQueuedThread() {
// handle only fast path, else relay
return (head == tail) ? null : fullGetFirstQueuedThread();
}
/**
* 获取队列线程
*/
private Thread fullGetFirstQueuedThread() {
/*
* The first node is normally head.next. Try to get its
* thread field, ensuring consistent reads: If thread
* field is nulled out or s.prev is no longer head, then
* some other thread(s) concurrently performed setHead in
* between some of our reads. We try this twice before
* resorting to traversal.
一般来说这个线程就是head->next,需要保证在并发情况下读一致性
1. (h = head) != null
2. (s = h.next) != null
3. s.prev = head
4. (st = s.thread) != null
假设2、3中间被并发的插入了一个setHead方法,执行3时发现s.prev为空了
因此,这里需要再试一次(第二次其实也有可能会失败,不过概率已经很小。
还有后面一道保障,就是下面的从tail开始向前遍历寻找
*/
Node h, s;
Thread st;
if (((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null) ||
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null))
return st;
/*
* Head's next field might not have been set yet, or may have
* been unset after setHead. So we must check to see if tail
* is actually first node. If not, we continue on, safely
* traversing from tail back to head to find first,
* guaranteeing termination.
从tail开始向前遍历寻找,保证在并发情况下读一致性
*/
Node t = tail;
Thread firstThread = null;
while (t != null && t != head) {
Thread tt = t.thread;
if (tt != null)
firstThread = tt;
t = t.prev;
}
return firstThread;
}
/**
判断线程是否在队列里(包含头节点了),直接从tail开始反向搜索
*/
public final boolean isQueued(Thread thread) {
if (thread == null)
throw new NullPointerException();
for (Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
}
/**
队列里第一个等待的结点是否是独占模式,从头往尾
*/
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
/**
判断自己是不是队列中最前面的线程
*/
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
// Instrumentation and monitoring methods
/**
队列的长度
*/
public final int getQueueLength() {
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
}
/**
获取同步队列线程集合,是一个估计值。
*/
public final Collection<Thread> getQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
/**
获取同步队列中独占模式线程集合,估计值。
*/
public final Collection<Thread> getExclusiveQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
/**
获取同步队列中共享模式线程集合,估计值
*/
public final Collection<Thread> getSharedQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
/**
* Returns a string identifying this synchronizer, as well as its state.
* The state, in brackets, includes the String {@code "State ="}
* followed by the current value of {@link #getState}, and either
* {@code "nonempty"} or {@code "empty"} depending on whether the
* queue is empty.
*
* @return a string identifying this synchronizer, as well as its state
*/
public String toString() {
int s = getState();
String q = hasQueuedThreads() ? "non" : "";
return super.toString() +
"[State = " + s + ", " + q + "empty queue]";
}
// Internal support methods for Conditions
/**
当前节点是否在sync等待队列中
*/
final boolean isOnSyncQueue(Node node) {
//如果waitStatus还是condition或者node.prev还是null,说明还在条件队列里
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
//如果next域有值了,说明已经挪到AQS队列里了
if (node.next != null) // If has successor, it must be on queue
return true;
/*
走到这里说明node.prev肯定不是null的了,但是还不能说明node就是AQS同步队列里。从tail开始寻找node节点
*/
return findNodeFromTail(node);
}
/**
从Sync队列尾部开始判断,因为在isOnSyncQueue方法调用该方法时,node.prev一定不为null。但这时的node可能还没有完全添加到Sync队列中(因为node.next是null),这时可能是在自旋中。
*/
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
/**
* Transfers a node from a condition queue onto sync queue.
* Returns true if successful.
* @param node the node
* @return true if successfully transferred (else the node was
* cancelled before signal)
* 唤醒节点
*/
final boolean transferForSignal(Node node) {
/*
* 首先尝试设置node的状态为0
* 如果设置失败,说明已经被取消,没必要再进入Sync队列了,doSignal中的循环会找到一个node再次执行;
* 如果设置成功,但之后又被取消了呢?无所谓,虽然会进入到Sync队列,但在获取锁的时候会调用shouldParkAfterFailedAcquire方法,该方法中会移除此节点。
*/
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
/**
* Transfers node, if necessary, to sync queue after a cancelled wait.
* Returns true if thread was cancelled before being signalled.
*
* @param node the node
* @return true if cancelled before the node was signalled
* 判断,在线程中断的时候,是否这时有signal方法的调用
*/
final boolean transferAfterCancelledWait(Node node) {
//如果compareAndSetWaitStatus(node, Node.CONDITION, 0)执行成功,则说明中断发生时,没有signal的调用,因为signal方法会将状态设置为0;
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
//将node添加到Sync队列中,并返回true,表示中断在signal之前;
enq(node);
return true;
}
/*
* If we lost out to a signal(), then we can't proceed
* until it finishes its enq(). Cancelling during an
* incomplete transfer is both rare and transient, so just
* spin.
* 如果上面失败,则检查当前线程的node是否已经在Sync队列中了,如果不在Sync队列中,则让步给其他线程执行,直到当前的node已经被signal方法添加到Sync队列中;
*/
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
/**
* Invokes release with current state value; returns saved state.
* Cancels node and throws exception on failure.
* @param node the condition node for this wait
* @return previous sync state
* 将之前加入的锁的次数全部释放,目的是将该线程从Sync队列中移出
*/
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
// Instrumentation methods for conditions
/**
* Queries whether the given ConditionObject
* uses this synchronizer as its lock.
*
* @param condition the condition
* @return {@code true} if owned
* @throws NullPointerException if the condition is null
*/
public final boolean owns(ConditionObject condition) {
return condition.isOwnedBy(this);
}
/**
* Queries whether any threads are waiting on the given condition
* associated with this synchronizer. Note that because timeouts
* and interrupts may occur at any time, a {@code true} return
* does not guarantee that a future {@code signal} will awaken
* any threads. This method is designed primarily for use in
* monitoring of the system state.
*
* @param condition the condition
* @return {@code true} if there are any waiting threads
* @throws IllegalMonitorStateException if exclusive synchronization
* is not held
* @throws IllegalArgumentException if the given condition is
* not associated with this synchronizer
* @throws NullPointerException if the condition is null
* 条件等待队列是否有节点在等待
*/
public final boolean hasWaiters(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.hasWaiters();
}
/**
* Returns an estimate of the number of threads waiting on the
* given condition associated with this synchronizer. Note that
* because timeouts and interrupts may occur at any time, the
* estimate serves only as an upper bound on the actual number of
* waiters. This method is designed for use in monitoring of the
* system state, not for synchronization control.
*
* @param condition the condition
* @return the estimated number of waiting threads
* @throws IllegalMonitorStateException if exclusive synchronization
* is not held
* @throws IllegalArgumentException if the given condition is
* not associated with this synchronizer
* @throws NullPointerException if the condition is null
* 获取等待队列长度
*/
public final int getWaitQueueLength(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitQueueLength();
}
/**
* Returns a collection containing those threads that may be
* waiting on the given condition associated with this
* synchronizer. Because the actual set of threads may change
* dynamically while constructing this result, the returned
* collection is only a best-effort estimate. The elements of the
* returned collection are in no particular order.
*
* @param condition the condition
* @return the collection of threads
* @throws IllegalMonitorStateException if exclusive synchronization
* is not held
* @throws IllegalArgumentException if the given condition is
* not associated with this synchronizer
* @throws NullPointerException if the condition is null
* 获取条件等待队列的线程
*/
public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitingThreads();
}
/**
ConditionObject在AbstractQueuedSynchronize里实现接口Condition,因为ConditionObject需要调用AbstractQueuedSynchronizer定义的方法。
*/
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
//表示Condition队列的头尾元素
/** First node of condition queue. */
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;
/**
* Creates a new {@code ConditionObject} instance.
*/
public ConditionObject() { }
// Internal methods
/**
把当前线程放入Condition队列中
*/
private Node addConditionWaiter() {
Node t = lastWaiter;
// 如果尾节点被取消,调用unlinkCancelledWaiters方法删除Condition队列中被cancel的节点
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
//根据当前线程创建一个Node并添加到Condition队列中
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)// 尾结点为空
firstWaiter = node;
else
t.nextWaiter = node;
// 更新condition队列的尾结点
lastWaiter = node;
return node;
}
/**
先将队列前面节点依次从队列中取出,然后调用transferForSignal方法去唤醒节点,这个方法有可能失败,因为等待线程可能已经到时或者被中断,因此while循环这个操作直到成功唤醒或队列为空。
*/
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
// 将结点从condition队列转移到sync队列失败并且condition队列中的头结点不为空,一直循环
}
/**
与doSignal方法比较一下,doSignal方法只是唤醒了一个node并加入到Sync队列中,而doSignalAll方法唤醒了所有的Condition节点,并加入到Sync队列中。
*/
private void doSignalAll(Node first) {
// condition队列的头结点尾结点都设置为空
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
// 将first结点从condition队列转移到sync队列
transferForSignal(first);
// 重新设置first
first = next;
} while (first != null);
}
/**
* Unlinks cancelled waiter nodes from condition queue.
* Called only while holding lock. This is called when
* cancellation occurred during condition wait, and upon
* insertion of a new waiter when lastWaiter is seen to have
* been cancelled. This method is needed to avoid garbage
* retention in the absence of signals. So even though it may
* require a full traversal, it comes into play only when
* timeouts or cancellations occur in the absence of
* signals. It traverses all nodes rather than stopping at a
* particular target to unlink all pointers to garbage nodes
* without requiring many re-traversals during cancellation
* storms.
* 把已取消的节点移除Condition队列。
*/
private void unlinkCancelledWaiters() {
// 保存condition队列头结点
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
// 设置t节点的额nextWaiter域为空
t.nextWaiter = null;
if (trail == null)
// 重新设置condition队列的头结点
firstWaiter = next;
else
// 设置trail结点的nextWaiter域为next结点
trail.nextWaiter = next;
if (next == null)
// 设置condition队列的尾结点
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
// public methods
/**
在该方法中判断当前线程是否占有独占锁,然后通过firstWaiter依次唤醒Condition队列中的node,并把node添加到Sync队列中。
*/
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
/**
判断当前线程是否占有独占锁,然后执行doSignalAll方法
*/
public final void signalAll() {
// 不被当前线程独占,抛出异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
// 唤醒一个等待线程
doSignalAll(first);
}
/**
await()与awaitUninterruptibly()最明显的区别就是抛出了InterruptedException异常。
要说awaitUninterruptibly()是用户在无需顾及中断的时候使用,那么await()就是在用户想要程序能够及时响应中断时使用。
*/
public final void awaitUninterruptibly() {
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if (Thread.interrupted())
//记录中断标识
interrupted = true;
}
//看是否要将中断标识再次设置为true
if (acquireQueued(node, savedState) || interrupted)
selfInterrupt();
}
/*
* For interruptible waits, we need to track whether to throw
* InterruptedException, if interrupted while blocked on
* condition, versus reinterrupt current thread, if
* interrupted while blocked waiting to re-acquire.
*/
/** Mode meaning to reinterrupt on exit from wait */
private static final int REINTERRUPT = 1;
/** Mode meaning to throw InterruptedException on exit from wait */
private static final int THROW_IE = -1;
/**
* Checks for interrupt, returning THROW_IE if interrupted
* before signalled, REINTERRUPT if after signalled, or
* 0 if not interrupted.
根据中断发生的时机返回后续需要处理这次中断的方式,如果发生中断,退出循环
*/
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}
/**
* Throws InterruptedException, reinterrupts current thread, or
* does nothing, depending on mod.
如果当前线程被中断,则在await方法中调用reportInterruptAfterWait方法
*/
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
/**
* Implements interruptible condition wait.
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
* <li> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled or interrupted.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li> If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
await方法首先根据当前线程创建了一个Node,然后释放当前线程的独占锁。
这里的savedState表示当前线程已经加锁的次数(ReentrantLock为重入锁)。
while循环其实就是一直判断,当前的线程是否又被添加到了Sync队列中,如果已经在Sync队列中,则退出循环。
*/
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// 根据当前线程创建一个Node添加到Condition队列中
Node node = addConditionWaiter();
// 释放当前线程的lock,从AQS的队列中移出
int savedState = fullyRelease(node);
int interruptMode = 0;
// 循环判断当前线程的Node是否在Sync队列中,如果不在,则park
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
//checkInterruptWhileWaiting方法根据中断发生的时机返回后续需要处理这次中断的方式,如果发生中断,退出循环
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// acquireQueued获取锁并返回线程是否中断, 如果线程被中断,并且中断的方式不是抛出异常,则设置中断后续的处理方式设置为REINTERRUPT
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
// 从头到尾遍历Condition队列,移除被cancel的节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
// 如果线程已经被中断,则根据之前获取的interruptMode的值来判断是继续中断还是抛出异常
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
/**
* Implements timed condition wait.
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
* <li> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li> If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
进行超时控制,功能与await类似,不同在于该方法中每次park是有时间限制的
*/
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return deadline - System.nanoTime();
}
/**
* Implements absolute timed condition wait.
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
* <li> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li> If interrupted while blocked in step 4, throw InterruptedException.
* <li> If timed out while blocked in step 4, return false, else true.
* </ol
根据给定的时间作为await的最后期限
*/
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (System.currentTimeMillis() > abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
LockSupport.parkUntil(this, abstime);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
/**
* Implements timed condition wait.
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
* <li> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li> If interrupted while blocked in step 4, throw InterruptedException.
* <li> If timed out while blocked in step 4, return false, else true.
* </ol>
有超时时间的await.
*/
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
timedout = transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
// support for instrumentation
/**
* Returns true if this condition was created by the given
* synchronization object.
*
* @return {@code true} if owned
*/
final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
return sync == AbstractQueuedSynchronizer.this;
}
/**
* Queries whether any threads are waiting on this condition.
* Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.
*
* @return {@code true} if there are any waiting threads
* @throws IllegalMonitorStateException if {@link #isHeldExclusively}
* returns {@code fals}程
查询是否有正在等待此条件的任何线程
*/
protected final boolean hasWaiters() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
return true;
}
return false;
}
/**
* Returns an estimate of the number of threads waiting on
* this condition.
* Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}.
*
* @return the estimated number of waiting threads
* @throws IllegalMonitorStateException if {@link #isHeldExclusively}
* returns {@code false}
返回正在等待此条件的线程数估计值
*/
protected final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
++n;
}
return n;
}
/**
* Returns a collection containing those threads that may be
* waiting on this Condition.
* Implements {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}.
*
* @return the collection of threads
* @throws IllegalMonitorStateException if {@link #isHeldExclusively}
* returns {@code false}
返回包含那些可能正在等待此条件的线程集合
*/
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
}
/**
* Setup to support compareAndSet. We need to natively implement
* this here: For the sake of permitting future enhancements, we
* cannot explicitly subclass AtomicInteger, which would be
* efficient and useful otherwise. So, as the lesser of evils, we
* natively implement using hotspot intrinsics API. And while we
* are at it, we do the same for other CASable fields (which could
* otherwise be done with atomic field updaters).
*/
//Unsafe类实例
private static final Unsafe unsafe = Unsafe.getUnsafe();
// state内存偏移地址
private static final long stateOffset;
// head内存偏移地址
private static final long headOffset;
// state内存偏移地址
private static final long tailOffset;
// tail内存偏移地址
private static final long waitStatusOffset;
// next内存偏移地址
private static final long nextOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
/**
* 如果队列为空,则通过CAS把当前Node设置成头节点
*/
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
/**
* 如果队列不为空,则向队列尾部添加Node
*/
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
/**
* 如果前驱节点正常,则修改前驱节点状态
*/
private static final boolean compareAndSetWaitStatus(Node node,
int expect,
int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset,
expect, update);
}
/**
* 比较并设置pred.next = next
*/
private static final boolean compareAndSetNext(Node node,
Node expect,
Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
}
五、思考几个问题:
(1)AQS内部维护的一个CLH队列的运作模式:
AQS内部维护一个CLH队列来管理锁。 线程会首先尝试获取锁,如果失败,则将当前线程以及等待状态等信息包成一个Node节点加到同步队列里。 接着会不断循环尝试获取锁(条件是当前节点为head的直接后继才会尝试),如果失败则会阻塞自己,直至被唤醒; 而当持有锁的线程释放锁时,会唤醒队列中的后继线程。
(2)waitStatus的设计原意:
waitStatus的设计背景其实就是:如果获取锁失败,判断是否应该挂起当前线程,挂起线程是有条件的。进而扩展出根据node不同的waitStatus,达到操作线程的目的.